This section discusses the functions and structures that allow you to use the timecode media handler.
The timecode media handler allows QuickTime movies to store timing information that is derived from the movie's original source material. Every QuickTime movie contains QuickTime-specific timing information, such as frame duration. This information affects how QuickTime interprets and plays the movie.
The timecode media handler allows QuickTime movies to store additional timing information that is not created by or for QuickTime. This additional timing information would typically be derived from the original source material--for example, as a SMPTE timecode. In essence, you can think of the timecode media handler as providing a link between the "digital" QuickTime-specific timing information and the original "analog" timing information from the source material.
A movie's timecode is stored in a timecode track. Timecode tracks contain
Apple Computer has defined the information that is stored in the track in a manner that is independent of any specific timecode standard. The format of this information is sufficiently flexible to accommodate all known timecode standards, including SMPTE timecoding. The timecode format information provides QuickTime the parameters for understanding the timecode and converting QuickTime time values into timecode time values (and vice versa).
One key timecode attribute relates to the technique used to synchronize timecode values with video frames. Most video source material is recorded at whole-number frame rates. For example, both PAL and SECAM video contain exactly 25 frames per second. However, some video source material is not recorded at whole-number frame rates. In particular, NTSC color video contains 29.97 frames per second (though it is typically referred to as 30 frames-per-second video). However, NTSC timecode values correspond to the full 30 frames-per-second rate; this is a holdover from NTSC black-and-white video. For such video sources, you need a mechanism that corrects the error that will develop over time between timecode values and actual video frames.
A common method for maintaining synchronization between timecode values and video data is called dropframe. Contrary to its name, the dropframe technique actually skips timecode values at a predetermined rate in order to keep the timecode and video data synchronized. It does not actually drop video frames. In NTSC color video, which uses the dropframe technique, the timecode values skip two frame values every minute, except for minute values that are evenly divisible by ten. So NTSC timecode values, which are expressed as HH:MM:SS:FF (hours, minutes, seconds, frames) skip from 00:00:59:29 to 00:01:00:02 (skipping 00:01:00:00 and 00:01:00:01). There is a flag in the timecode definition structure that indicates whether the timecode uses the dropframe technique.
You can make the toolbox display the timecode when a movie is played. Use the TCSetTimeCodeFlags function to turn the timecode display on and off. Note that the timecode track must be enabled for this display to work.
You store the timecode's source identification information in a user data item. Create a user data item with a type value of TCSourceRefNameType . Store the source information as a text string. This information might contain the name of the videotape from which the movie was created, for example. For more information about working with user data, see Inside Macintosh: QuickTime.
The timecode media handler provides functions that allow you to manipulate the source identification information. The following sample code demonstrates one way to set the source tape name in a timecode media's sample description.
void setTimeCodeSourceName (Media timeCodeMedia,
TimeCodeDescriptionHandle tcdH,
Str255 tapeName, ScriptCode tapeNameScript)
{
UserData srcRef;
if (NewUserData(&srcRef) == noErr) {
Handle nameHandle;
if (PtrToHand(&tapeName[1], &nameHandle, tapeName[0]) == noErr) {
if (AddUserDataText (srcRef, nameHandle,'name', 1,
tapeNameScript) == noErr) {
TCSetSourceRef (GetMediaHandler (timeCodeMedia),
tcdH,
srcRef);
}
DisposeHandle(nameHandle);
}
DisposeUserData(srcRef);
}
}
You can create a timecode track and media in the same manner that you create any other track. Call the NewMovieTrack function to create the timecode track, and use the NewTrackMedia function to create the track's media. Be sure to specify a media type value of TimeCodeMediaType when you call the NewTrackMedia function.
You can define the relationship between a timecode track and one or more movie tracks using the toolbox's new track reference functions (see "Track References" and "Functions for Working With Track References" elsewhere in this chapter for more information). You then proceed to add samples to the track, as appropriate.
Each sample in the timecode track provides timecode information for a span of movie time. The sample includes duration information. As a result, you typically add each timecode sample after you have created the corresponding content track or tracks.
The timecode media sample description contains the control information that allows QuickTime to interpret the samples. This includes the timecode format information. The actual sample data contains a frame number that identifies one or more content frames that use this timecode. Stored as a long , this value identifies the first frame in the group of frames that use this timecode. In the case of a movie made from source material that contains no edits, you would only need one sample. When the source material contains edits, you typically need one sample for each edit, so that QuickTime can resynchronize the timecode information with the movie. Those samples contain the frame numbers of the frames that begin each new group of frames.
The timecode description structure defines the format and content of a timecode media sample description, as follows:
typedef struct TimeCodeDescription {
long descSize; /* size of the structure */
long dataFormat; /* sample type */
long resvd1; /* reserved--set to 0 */
short resvd2; /* reserved--set to 0 */
short dataRefIndex; /* data reference index */
long flags; /* reserved--set to 0 */
TimeCodeDef timeCodeDef; /* timecode format information */
long srcRef[1]; /* source information */
} TimeCodeDescription, *TimeCodeDescriptionPtr, **TimeCodeDescriptionHandle;
The timecode definition structure contains the timecode format information. This structure is defined as follows:
typedef struct TimeCodeDef {
long flags; /* timecode control flags */
TimeScale fTimeScale; /* timecode's time scale */
TimeValue frameDuration; /* how long each frame lasts */
unsigned char numFrames; /* number of frames per second */
} TimeCodeDef;
The best way to understand how to format and interpret the timecode definition structure is to consider an example. If you were creating a movie from an NTSC video source recorded at 29.97 frames per second, using SMPTE timecodes, you would format the timecode definition structure as follows:
TimeCodeDef.flags = tcDropFrame | tc24HourMax;
TimeCodeDef.fTimeScale = 2997; /* units */
TimeCodeDef.frameDuration = 100; /* relates units to frames */
TimeCodeDef.numFrames = 30; /* whole frames per second */
The movie's natural frame rate of 29.97 frames per second is obtained by dividing the fTimeScale value by the frameDuration (2997 / 100). Note that the flags field indicates that the timecode uses the dropframe technique to resync the movie's natural frame rate of 29.97 frames per second with its playback rate of 30 frames per second.
Given a timecode definition, you can freely convert from frame numbers to time values and from time values to frame numbers. For a time value of 00:00:12:15 (HH:MM:SS:FF), you would obtain a frame number of 375 ((12*30) + 15). The timecode media handler provides a number of functions that allow you to perform these conversions.
When you use the timecode media handler to work with time values, the media handler uses timecode records to store the time values. The timecode record allows you to interpret the time information as either a time value (HH:MM:SS:FF) or a counter value. The timecode record is defined as follows:
typedef union TimeCodeRecord {
TimeCodeTime t; /* value interpreted as time */
TimeCodeCounter c; /* value interpreted as counter */
} TimeCodeRecord;
typedef struct TimeCodeTime {
unsigned char hours; /* time: hours */
unsigned char minutes; /* time: minutes */
unsigned char seconds; /* time: seconds */
unsigned char frames; /* time: frames */
} TimeCodeTime;
typedef struct TimeCodeCounter {
long counter; /* counter value */
} TimeCodeCounter;
When you are working with timecodes that allow negative time values, the minutes field of the TimeCodeTime structure ( TimeCodeRecord.t.minutes ) indicates whether the time value is positive or negative. If the tctNegFlag bit of the minutes field is set to 1, the time value is negative.
The TCGetCurrentTimeCode function retrieves the timecode and source identification information for the current movie time.
pascal HandlerError TCGetCurrentTimeCode (MediaHandler mh, long *frameNum, TimeCodeDef *tcdef,
TimeCodeRecord *tcrec, UserData *srcRefH);
The TCGetTimeCodeAtTime function returns a track's timecode information corresponding to a specific media time.
pascal HandlerError TCGetTimeCodeAtTime (MediaHandler mh, TimeValue mediaTime, long *frameNum,
TimeCodeDef *tcdef, TimeCodeRecord *tcdata, UserData *srcRefH);
The TCTimeCodeToFrameNumber function converts a timecode time value into its corresponding frame number.
pascal HandlerError TCTimeCodeToFrameNumber (MediaHandler mh, TimeCodeDef *tcdef,
TimeCodeRecord *tcrec, long *frameNumber);
The TCFrameNumberToTimeCode function converts a frame number into its corresponding timecode time value.
pascal HandlerError TCFrameNumberToTimeCode (MediaHandler mh, long frameNumber,
TimeCodeDef *tcdef, TimeCodeRecord *tcrec);
The TCTimeCodeToString function converts a time value into a text string (HH:MM:SS:FF). If the timecode uses the dropframe technique, the separators are semicolons (;) rather than colons (:).
pascal HandlerError TCTimeCodeToString(MediaHandler mh, TimeCodeDef *tcdef,
TimeCodeRecord *tcrec, StringPtr tcStr);
The TCSetSourceRef function allows you to change the source information in the timecode media sample reference.
pascal HandlerError TCSetSourceRef (MediaHandler mh, TimeCodeDescriptionHandle tcdH,
UserData srefH);
The TCGetSourceRef function allows you to retrieve the source information from the timecode media sample reference.
pascal HandlerError TCGetSourceRef (MediaHandler mh, TimeCodeDescriptionHandle tcdH,
UserData *srefH);
The TCSetTimeCodeFlags function allows you to change the flags that affect how the toolbox handles the timecode information.
pascal HandlerError TCSetTimeCodeFlags (MediaHandler mh, long flags, long flagsMask);
The TCGetTimeCodeFlags function allows you to retrieve the timecode control flags.
pascal HandlerError TCGetTimeCodeFlags (MediaHandler mh, long *flags );
The TCSetDisplayOptions function allows you to set the text characteristics that apply to timecode information that is displayed in a movie.
pascal HandlerError TCSetDisplayOptions (MediaHandler mh, TCTextOptionsPtr textOptions);
You provide the text style information in a text options structure. This structure is defined as follows:
typedef struct TCTextOptions {
short txFont; /* font */
short txFace; /* font style */
short txSize; /* font size */
RGBColor foreColor; /* foreground color */
RGBColor backColor; /* background color */
} TCTextOptions, *TCTextOptionsPtr;
For more information about working with text characteristics, see Inside Macintosh: Text.
The TCGetDisplayOptions function allows you to retrieve the text characteristics that apply to timecode information that is displayed in a movie.
pascal HandlerError TCGetDisplayOptions (MediaHandler mh, TCTextOptionsPtr textOptions);
| Previous | Chapter Contents | Chapter Top | Next |